
const Fn = require('./fs/fn.js')
if (!global.sleep) global.sleep = async (ttl) => { return await new Promise(res => { setTimeout(res, ttl) }) }
const fs = require('fs')
const cp = require('child_process')
const zstFile = 'D:/git/adb/data/tt/test/20200627/04/rand.zst'
const buf = fs.readFileSync(zstFile)
console.log(buf.length)
const p = cp.spawn('zstd', ['-d', '-c'], { maxBuffer: 1024 * 1024 * 1024 })
p.stdout.on('data', async(data) => {
  // if (data.length < 131072) 
  console.log(data.slice(0, 20), data.slice(-20), data.length, Fn._t() - _t)
  p.stdout.pause()
})
p.on('error', (e) => {
  console.log('error:', e)
})
p.on('exit', (e) => {
  console.log('exit:', e)
})
p.on('close', (e) => {
  console.log('close:', e, Fn._t() - _t)
})
p.stdin.on('error', (e) => {
  console.log('stdin error:', e)
})
p.stdout.on('end', (e) => {
  console.log('stdout end:', e)
})
p.stdout.on('exit', (e) => {
  console.log('stdout exit:', e)
})
let _t = Fn._t()
p.stdin.write(buf)
setTimeout(() => {
  _t = Fn._t()
  p.stdin.write(buf)
}, 10000)
return
// const p = cp.spawn('zstd', ['-d', '-c', 'D:/git/adb/data/tt/test/20200627/04/rand.zst'], { maxBuffer: 500 * 1024 * 1024 })
// p.stdout.on('data', async(data) => {
//   console.log(data.length, Fn._t() - _t)
//   p.stdout.pause()
//   // await sleep(10)
//   // p.stdout.resume()
// })
return
// var buf = Buffer.alloc(1000 * 1000 * 100)
// const t = buf.slice(1,100)
// setTimeout(() => {
//   buf = Buffer.alloc(1000 * 1000 * 1)
//   const t = buf.slice(1,100)
// }, 1000)
// setTimeout(() => {
//   buf = Buffer.alloc(1000 * 1000 * 25)
// }, 3000)
// // setTimeout(() => {
// //   buf = undefined
// // }, 5000)
// return setInterval(() => {
//   console.log(process.memoryUsage().arrayBuffers/1024/1024)
// }, 1000)


require('./lib/Adebug')
const Acan = require('./lib/Acan')
const http = require('http')
const io = require('socket.io-client')
const { fstat } = require('fs')
const agent = new http.Agent({ keepAlive: true, maxFreeSockets: 5000, keepAliveMsecs: 10000, timeout: 10000 })

const conf = { loop: process.argv[2] || 'all', ttl: parseInt(process.argv[3] || 50), num: parseInt(process.argv[4] || 2), protocol: process.argv[5] || 'io' }

const errFn = (e) => {
  if (e.code === 'ECONNREFUSED') return // console.log(e)
  console.log(e)
}

let geti = 0
let findi = 0
let findLast = 0
let upLen = 0
let upLastLen = 0
let getLen = 0
let getLast = 0
let getLastLen = 0
setInterval(() => {
  console.log('qps:', geti - getLast, findi - findLast, 'down:', ((getLen - getLastLen) / 1024).toFixed(2), 'kb/s', 'up:', ((upLen - upLastLen) / 1024).toFixed(2), 'kb/s')
  getLast = geti
  findLast = findi
  getLastLen = getLen
  upLastLen = upLen
}, 1000)
const httpGet = (url, obj) => {
  const req = http.request(url + '?' + Acan.url.unite(obj), { agent }, (res) => {
    geti++
    if (res.statusCode === 200) return
    // console.log(res.statusCode)
  })
  req.on('error', errFn)
  req.end()
  return req
}
const httpPost = (url, obj, post) => {
  const req = http.request(url + '?' + Acan.url.unite(obj), { method: 'POST', agent, headers: {"Connection":"Keep-Alive"} }, (res) => {
    if (url.includes('/creates')) geti += post.length
    else geti++
    upLen += JSON.stringify(post).length
    if (res.statusCode === 200) return
    res.setEncoding('utf8')
    res.on('data', (data) => {
      console.log(JSON.parse(data))
    })
  })
  req.on('error', errFn)
  req.end(JSON.stringify(post))
  return req
}

const nrr = ['test', 'test', 'haha', 'hehe', 'hello']

const createData = (ti) => {
  return {
    name: nrr[Acan.random(0, nrr.length - 1)],
    rt: Acan.random(0, 1),
    uptime: process.uptime(),
    test: Acan.random(1000, 9999).toString(32) + '-' + ti,
    rand: '-' + Acan.random(0, 1699999999),
    bool: !!Acan.random(0, 1),
    int: Acan.random(0, 99),
    time: Acan.time(),
    date: Acan.time('Y-m-d H:i:s')
  }
}

const loop = async(c, times) => {
  console.log('Start creates')
  let ti = 0
  const post = []
  for (let i = 0; i < conf.num; i++) {
    const data = createData(ti)
    // if (i < 20) c.emit('create', 'tt.test', data, (rs) => {
    //   if (!rs) return
    //   geti++
    //   c.emit('update', 'tt.test', { _id: rs._id }, { test: 'update' }, () => { geti++ })
    // })
    // httpPost('http://127.0.0.1:7170/tt.test/create', {}, data)
    post.push(data)
  }
  const len = JSON.stringify(post).length
  while(true) {
    await sleep(conf.ttl)
    if (times && ti >= times) return console.log('插入完成')
    if (conf.protocol === 'io') c.emit('creates', 'tt.test', post, (rs) => {
      if (!rs.count) return console.log(rs)
      geti += rs.count
      upLen += len
      getLen += JSON.stringify(rs).length
    })
    else httpPost('http://127.0.0.1:7170/tt.test/creates', {}, post)
    ti++
  }
}

const loopCreate = async(c, times) => {
  console.log('Start create')
  let ti = 0
  while(true) {
    await sleep(conf.ttl)
    if (times && ti >= times) return console.log('插入完成')
    const post = []
    for (let i = 0; i < conf.num; i++) {
      const data = createData(ti)
      c.emit('create', 'tt.test', data, (rs) => {
        if (!rs) return
        geti++
        upLen += JSON.stringify(data).length
      })
    }
    ti++
  }
}

const loopCreateUp = async(c, times) => {
  console.log('Start createUp')
  let ti = 0
  while(true) {
    await sleep(conf.ttl)
    if (times && ti >= times) return console.log('插入完成')
    const post = []
    for (let i = 0; i < conf.num; i++) {
      const data = createData(ti)
      c.emit('create', 'tt.test', data, (rs) => {
        if (!rs) return
        geti++
        upLen += JSON.stringify(data).length
        if (i < 50) c.emit('update', 'tt.test', { _id: rs._id }, { test: 'update' }, () => { geti++ })
      })
    }
    ti++
  }
}

const loopFind = async(c) => {
  console.log('Start Find')
  while(true) {
    await sleep(conf.ttl)
    for (let i = 0; i < conf.num; i++) {
      if (conf.protocol === 'io') c.emit('findOne', 'tt.test', (data) => { findi++; getLen += JSON.stringify(data).length })
      else httpGet('http://127.0.0.1:7170/tt.test/findOne', {})
      // c.emit('find', 'tt.test', (data) => { findi++; getLen += JSON.stringify(data).length })
    }
  }
}

const pool = () => {
  const client = io('http://127.0.0.1:7170')
  client.on('connect', () => {
  //   client.emit('createTable', 'tt.test2', {
  //     name: { len: 10, type: 'string', encoding: 'utf8'},
  //     rt: { len: 1, type: 'int'},
  //     uptime: { type: 'double'},
  //     test: { len: 20, type: 'string', encoding: 'utf8'},
  //     rand: { len: 20, type: 'string', encoding: 'utf8'},
  //     bool: { type: 'bool', default: false },
  //     int: { len: 2, type: 'int' }, // int len: 1-6, 1: 128, 2: 128 * 256, 3: 128 * 256 * 256
  //     time: { type: 'time' },
  //     date: { len: 20, type: 'string', encoding: 'utf8'}
  //   }, { update: true, tableMem: 10 }, (rs) => {
  //     Adebug.log('createTable test ok', rs)
  //   })
  })
  setTimeout(() => {
    if (['find', 'all'].includes(conf.loop)) loopFind(client)
    if (['creates', 'all'].includes(conf.loop)) loop(client)
    if (['create', 'all'].includes(conf.loop)) loopCreate(client)
    if (['createUp', 'all'].includes(conf.loop)) loopCreateUp(client)
  }, 100)
}
pool()


// client.emit('createTable', 'apix.log-apix', {
//   rt: { len: 1, type: 'int' }, // int len: 1-6, 1: 128, 2: 128 * 256, 3: 128 * 256 * 256
//   ip0: { len: 8, type: 'string', encoding: 'utf8' },
//   ip1: { len: 8, type: 'string', encoding: 'utf8' },
//   ip2: { len: 8, type: 'string', encoding: 'utf8' },
//   os: { len: 8, type: 'string', encoding: 'utf8' },
//   osVer: { len: 10, type: 'string', encoding: 'utf8' },
//   br: { len: 20, type: 'string', encoding: 'utf8' },
//   brVer: { len: 20, type: 'string', encoding: 'utf8' },
//   dvTp: { len: 10, type: 'string', encoding: 'utf8' },
//   dv: { len: 20, type: 'string', encoding: 'utf8' }, // 型号
//   u: { len: 6, type: 'string', encoding: 'utf8' }, // 渠道id
//   at: { len: 1, type: 'int' }, //
//   o: { len: 1, type: 'int' }, //
//   imei: { len: 20, type: 'string', encoding: 'utf8' },
//   oimei: { len: 20, type: 'string', encoding: 'utf8' },
//   ip: { len: 15, type: 'string', encoding: 'utf8' },
//   ua: { len: 200, type: 'string', encoding: 'utf8' },
//   cf: { len: 30, type: 'string', encoding: 'utf8' },
//   cfid: { len: 40, type: 'string', encoding: 'utf8' },
//   cfad: { len: 40, type: 'string', encoding: 'utf8' },
//   isApp: { type: 'bool', default: false }
// }, { update: true, tableMem: 200 }, (rs) => {
//   Adebug.log('creatTable apix ok', rs)
// })


// gzip
// win10 单核最大 creates 10 * 2000: 18000/s  create 10 * 100: 8000/s
// win10 双核最大 findOne: 50000, find limit 10: 3200
// ubuntu 单核最大 creates 20 * 1000: 40000  create 10 * 500: 20000/s
// ubuntu 单核最大 findOne: 36000, find limit 10: 